#include "EmulatorInit.h"

Module* initializeModule(void)
{
  LLVMContext &Context = getGlobalContext();
  return new Module(StringRef("TraceModule"), Context); 
}

ExecutionEngine* initializeExecutionEngine(void)
{
  ExecutionEngine *EE = 0;
  LLVMContext &Context = getGlobalContext();

  // If we have a native target, initialize it to ensure it is linked in and
  // usable by the JIT.
  InitializeNativeTarget();

  // Prepare emulator JIT structures.
  std::string ErrorMsg;
  Module *Mod = new Module(StringRef("TraceModule"), Context); 
  Mod->setTargetTriple(sys::getDefaultTargetTriple());

  EngineBuilder builder(Mod);
  builder.setRelocationModel(Reloc::Default);
  builder.setCodeModel(CodeModel::JITDefault);
  builder.setErrorStr(&ErrorMsg);
  builder.setJITMemoryManager(JITMemoryManager::CreateDefaultMemManager());
  builder.setEngineKind(EngineKind::JIT);
  builder.setOptLevel(CodeGenOpt::Aggressive);

  EE = builder.create();
  if (!EE) {
#if 0
    if (!ErrorMsg.empty())
      errs() <<  "EmulatorJIT: error creating EE: " << ErrorMsg << "\n";
    else
      errs() <<  "EmulatorJIT: unknown error creating EE!\n";
    // Simply return, this will be caught by the interpreter and the emulator
    // will terminate.
#endif
    return 0;
  }

  // The following functions have no effect if their respective profiling
  // support wasn't enabled in the build configuration.
  EE->RegisterJITEventListener(
                JITEventListener::createOProfileJITEventListener());
  EE->RegisterJITEventListener(
                JITEventListener::createIntelJITEventListener());

  // Run static constructors.
  EE->runStaticConstructorsDestructors(false);

  return EE;
}

EmulatorIRGenerator* initializeIRGenerator(void)
{
  return EmulatorIRGenerator::CreateDefaultIRGenerator(); 
}

EmulatorInterpreter* initializeInterpreter(void)
{
  return EmulatorInterpreter::CreateDefaultInterpreter(); 
}

EmulatorCodeGenerator* initializeCodeGenerator(void)
{
  // Get a code generator.
  EmulatorCodeGenerator *EmuCodeGen = 0;
  EmuCodeGen = EmulatorCodeGenerator::CreateDefaultCodeGenerator();

  // Set up the JIT specific code snippet.
  uint32_t estimatedSize = EmuCodeGen->estimateRequiredCodeSize();
  void *mem = getGlobalEE()->allocateFromMemoryManager(estimatedSize);
  EmuCodeGen->initialize(mem, estimatedSize);

  return EmuCodeGen;
}

